<?php

class Third_EntityXml{
	public $arrayToXml = null;
	
	private $action;
	
	public function __construct( $dataBase = "", $tableName = "", $entity = ""){
		if( $dataBase )  $this->setDataBase( $dataBase );
		if( $tableName ) $this->setTableName( $tableName );
		if( $entity ) $this->setEntity( $entity );		
		
		$this->setConfigDefaultValues();
		
	}
	
	public function setDataBase( $dataBase ){
		$this->dataBase  =  $dataBase;
	}
	
	public function setAction( $action ){
		$this->action = $action ;
	}
	
	public function getAction()	{
		return $this->action;
	}

	public function setEntity( $entity ){
		$this->entity = $entity ;
	}
	
	public function setTableName( $tableName ){
		$this->tableName = $tableName ;
	}
	
	public function getTableName()	{
		return ( isset($this->tableName) )? $this->tableName : '';
	}

	public function loadFields(  ){
		$query = "SHOW FULL COLUMNS FROM ".$this->getTableName();
		$this->dataBase->expression( $query );

			for( $i=0; $i < $this->dataBase->getRows(); $i++ ) {
				$this->dataBase->fetch($i);
	
				$data["Type"] 		= $this->dataBase->data['Type']; 
				$data["Null"] 		= $this->dataBase->data['Null']; 
				$data["Key"] 		= $this->dataBase->data['Key']; 
				$data["Default"] 	= $this->dataBase->data['Default']; 
				
				$this->fields[ $this->dataBase->data['Field'] ] = $data;
				
			}
			
			return $this->fields;
	}
	
	public function loadFieldsFromTable( $tableName ){
		$dataBase = $this->dataBase;
		
		$query = "SHOW FULL COLUMNS FROM $tableName";

		try{
			$dataBase->expression( $query );
		} catch (Exception $e){
			$dataBase->error($e->getMessage());
		}	
		
		for( $i=0; $i < $dataBase->getRows(); $i++ ) {
			$dataBase->fetch($i);

			$fields[] = $dataBase->data['Field'];
			
		}
		
		return $fields;
	}
	
	function getComponent($type , $key ){
	
		$type = reset( explode( '(', $type ) );
		
		switch($type){
			case 'int':
				$type = 'input';
			break;
			case 'varchar':
				$type = 'input';
			break;
			case 'enum':
				$type = 'select';
			break;
			case 'text':
				$type = 'textarea';
			break;
			default:
				$type = 'input';
			break;	
		}
		
		switch($key){
			case 'MUL':
				$type = 'select';
			break;
		}
		
		return $type;
	}
	
	function getType( $key ){
		
		switch( $key ){
			case 'PRI':
				$type = 'hidden';
			break;
			default:
				$type = 'text';
			break;
		}
		
		return $type;
	}
	
	function getRequired($type){
		$type = reset( explode( '(', $type ) );
		switch($type){
			case 'NO':
				$required = 'true';
			break;
			default:
				$required = 'false';
			break;
		}
		return $required;
	}
	
	function getPattern( $key, $type){
		
		$type = reset( explode( '(', $type ) );
		
		switch($key){
			case 'PRI':
				$pattern = 'hidden';
			break;
			case 'MUL':
				$pattern = 'Fki';
			break;
		}
		switch($type){
			case 'enum':
				$pattern = 'Enum';
			break;
		}		
		
		return $pattern;
	}
	
	function getValues($type){
		return Third_Funcs::array_map_tree( 'utf8_encode', enumValue( $type , "list" ) );
	}
	
	function getMaxLength($type){
		$valor = (int) entre( '(', ')', $type );
		
		if(!$valor)
			$valor = '20';
			
		return $valor;
	}
	
	function getSize($type){
		$valor = $this->getMaxLength( $type );
		
		if($valor > 60)
			$valor = '60';
			
		return $valor;
	}
	
	function getRelationFieldKey( $table_name ){
		$sql = "SHOW KEYS FROM ".$table_name." FROM ".$this->dataBase->getDataBase( )." WHERE Key_name = 'PRIMARY'";
		$data = $this->dataBase->execute( $sql );

		return $data[0]['Column_name'];
	}
	
	function getRelation($key, $fieldName, $method = false){

		if($key == 'MUL'){
			$sql = "
				SELECT 
			       CONSTRAINT_NAME as name,
			       REFERENCED_TABLE_SCHEMA as db,
			       REFERENCED_TABLE_NAME as 'table',
			       REFERENCED_COLUMN_NAME as 'field'
			   FROM `information_schema`.`KEY_COLUMN_USAGE` 
			       WHERE CONSTRAINT_SCHEMA = '".$this->dataBase->getDataBase( )."' 
			             AND TABLE_NAME    = '".$this->getTableName()."'
			             AND COLUMN_NAME   = '".$fieldName."'
			             AND CONSTRAINT_NAME <> 'PRIMARY'
			             AND REFERENCED_TABLE_NAME IS NOT NULL ;";

					$data = $this->dataBase->execute( $sql );
					
					if($method){
						return $data;
					} else{
						//SALVA O NOME DA RELAÇÃO
						$field_mul_name = $fieldName."_field_name";
						$this->$field_mul_name = $data[0]['name'];
						
						return $data[0]['table'];
					}		
		}
	}
	
	function setConfigValues( $array ){
		foreach($array as $key=>$value){
			if(!empty($value) )
				$this->$key	= $value;
		}	
	}
	
	function setConfigDefaultValues(){
		$this->file			= $this->getTableName().'.xml';
		$this->name			= p_maiscula( $this->getTableName() );
		$this->reference 	= $this->getTableName();
		$this->class		= p_maiscula( $this->getTableName(), $mode = 2 );
		$this->table		= $this->getTableName();
	}
	
	function getXmlConfigs( $mode ){
		switch($mode){
			case 'xml':
				$this->setConfigValues( $this->entity->configs );
			break;
		}

		$node = "
			<configs>
				<file		value=\"". $this->file		."\">Arquivo de configuração</file>	
				<name		value=\"". $this->name		."\">Nome entidade</name>
				<reference	value=\"". $this->reference	."\">Referencia da entidade</reference>
				<class		value=\"". $this->class		."\">Classe da entidade</class>
				<table		value=\"". $this->table		."\">Tabela no banco de dados</table>
			</configs>
		";
		
		return $node;
	}
	
	function setFieldValues( $array ){
		foreach($array as $key=>$value)
			$this->$key	= $value;
	}
	
	function setFieldDefaultValues( $fieldName ){
		
		$field = $this->fields[$fieldName];
		
		$type 		= $field["Type"];
		$required 	= $field["Null"];
		$key 		= $field["Key"];
		$default 	= $field["Default"];

		// Properties
		$this->component 		= $this->getComponent( $type , $key );
		$this->type		 		= $this->getType($key);
		$this->required 		= $this->getRequired($required);
		$this->pattern 			= $this->getPattern( $key, $type ); 
		$this->default 			= $default;
		$this->values			= $this->getValues($type);
		$this->size 			= $this->getSize($type);
		$this->maxlength 		= $this->getMaxLength($type);
		$this->relation 		= $this->getRelation($key, $fieldName);

		$field_mul_name 		= $fieldName."_field_name";
		$this->label 			= $this->$field_mul_name ? $this->$field_mul_name : $fieldName;
		
		$this->relation_field 	= "nome";
		$this->relation_key 	= $this->getRelationFieldKey( $this->relation );		
		$this->relation_query 	= "";
		$this->display			= "true";
		$this->message			= "";
		$this->transient		= "false";
		$this->rows				= 4;
		$this->hint				= "";
		$this->multiple			= "false";
		$this->params			= "";
		$this->fk_type			= $key;
		
		// ListOptions
		$this->showList			= "true";
		$this->width			= 60;
		$this->sortable			= "true";
		$this->editable			= "false";
		
		//Actions
		$this->onFocus			= "";
		$this->onBlur			= "";
		$this->onClick			= "";
		$this->onChange			= "";
		$this->onKeyPress		= "";
		$this->accessKey		= "";
		
		//Validations
		$this->validation_type	= "";		
		$this->minlength		= "";
		$this->maxlength		= $this->getMaxLength($type);
		$this->rangelength		= "";
		$this->equalTo			= "";
		$this->min				= "";
		$this->max				= "";
		$this->range			= "";
		$this->digits			= "false";
		$this->remote			= "";
		$this->accept			= "";
		$this->regex			= "";		
	}

	
	function getFieldXML( $fieldName ){
	
		$node = "
			<$fieldName>
				<properties value=\"Propriedades\">
					<label 		value = \"". $this->label		."\">Nome de exibição</label>
					<display  	value = \"". $this->display 	."\">Exibir no formulário</display>
					<required 	value = \"". $this->required 	."\">Obrigatorio</required>					
					<component	value = \"". $this->component 	."\">Componente</component>
					<type  		value = \"". $this->type  		."\">Tipo de campo</type>
					<pattern  	value = \"". $this->pattern  	."\">Padrão</pattern>
					<default  	value = \"". $this->default 	."\">Valor padrão</default>
					<values  	value = \"". $this->values 		."\">Valores (Enumeração) </values>
					<message  	value = \"". $this->message 	."\">Mensagem</message>
					<transient 	value = \"". $this->transient 	."\">Somente campo de formulário?</transient>
					<size  		value = \"". $this->size	 	."\">Tamanho de exibição:</size>
					<maxlength	value = \"". $this->maxlength 	."\">Tamanho máximo</maxlength>
					<rows  		value = \"". $this->rows	 	."\">Linhas</rows>
					<hint 		value = \"". $this->hint	 	."\">Dica de preenchimento</hint>
					<multiple	value = \"". $this->hint	 	."\">Permitir valores Multiplo</multiple>
					<params 	value = \"". $this->params	 	."\">Parâmentros extras</params>
					<fk_type 	value = \"". $this->fk_type 	."\">Tabela relacionada</fk_type>
					<relation 	value = \"". $this->relation 	."\">Tabela relacionada</relation>
					<relation_field	value = \"". $this->relation_field 	."\">Tabela relacionada</relation_field>
					<relation_key	value = \"". $this->relation_key ."\">Tabela relacionada</relation_key>
					<relation_query	value = \"". $this->relation_query 	."\">Query para preenchimento de campo</relation_query>
				</properties>
				<listOptions value=\"Opções de listagem\">
					<showList 	value = \"". $this->showList 	."\">Exibir na listagem</showList>
					<width 		value = \"". $this->width 		."\">Largura da coluna</width>
					<sortable 	value = \"". $this->sortable 	."\">Ordenável</sortable>
					<editable 	value = \"". $this->editable 	."\">Editável</editable>
				</listOptions>
				<actions value=\"Ações\">
					<onFocus 		value = \"". $this->onFocus 	."\">Ao entrar no campo</onFocus>
					<onBlur 		value = \"". $this->onBlur 		."\">Ao sair do campo</onBlur>
					<onClick 		value = \"". $this->onClick 	."\">Ao clicar</onClick>
					<onChange 		value = \"". $this->onChange 	."\">Ao selecionar</onChange>
					<onKeyPress 	value = \"". $this->onKeyPress 	."\">Enquanto digita</onKeyPress>
					<accessKey  	value = \"". $this->accessKey 	."\">Tecla de acesso</accessKey>
				</actions>
				<validations value=\"Validações\">
					<validation_type value = \"". $this->validation_type ."\">Tipo de validação</validation_type>			
					<minlength 		value = \"". $this->minlength 	."\">Valor mínimo (Numérico)</minlength>
					<maxlength 		value = \"". $this->maxlength 	."\">Valor máximo(Numérico)</maxlength>
					<rangelength	value = \"". $this->rangelength ."\">Valor de tamanho entre: </rangelength>  <!-- [13, 26] -->
					<equalTo 		value = \"". $this->equalTo 	."\">Igual a</equalTo>
					<min 			value = \"". $this->min 		."\">tamanho mínimo</min>
					<max 			value = \"". $this->max 		."\">tamanho máximo</max>
					<range 			value = \"". $this->range 		."\">Valores entre:</range> <!-- [13, 26] -->					
					<digits 		value = \"". $this->digits 		."\">tamanho máximo</digits>
					<remote 		value = \"". $this->remote 		."\">Arquivo de validação remoto</remote>
					<accept 		value = \"". $this->accept 		."\">Extensões aceitas</accept>
					<regex			value = \"". $this->regex 		."\">Expressão regular</regex>			
				</validations>
			</$fieldName>
		";
		
		return $node;
	}
	
	function getFieldsName(){
		
		if( is_array( $this->arrayFields ) && $this->generateMode == 'array' ){
			foreach($this->arrayFields as $key=>$value)
				$setted_fields[$value] = '';
				
			$this->fields = array_intersect_key($this->fields, $setted_fields );	
		}
			
		if($this->fields)
			return array_keys( $this->fields );
	}
	
	function getXmlFields( $mode = 'data_base' ){

		$this->generateMode = $mode;

		switch($mode){
			case 'data_base':
				
				$this->setConfigDefaultValues();
				
				if($this->dataBase){
					$this->loadFields( );
					$fieldsName = $this->getFieldsName();

					if( is_array( $this->arrayFields ) && is_array( $fieldsName ) ){
						
						$keys_to_do = array_keys( $this->arrayFields );
						foreach ($keys_to_do as $value){
							if( array_search($value, $fieldsName) ){
								$return[] = $value;
							} else {
								$return[] = $value;
							}
						}
						$fieldsName = $return;
						
					} else if( is_array( $this->arrayFields ) && !is_array( $fieldsName ) ){
						$fieldsName = $this->arrayFields;
					}
					
					if(is_array($fieldsName)){
						$fields .= "<fields>";	
			
							foreach($fieldsName  as $value ){

								if( is_array( $this->arrayFields[$value] ) ){
									$this->setFieldValues( $this->arrayFields[$value] );
									
								} else {
									$this->setFieldDefaultValues( $value );
								}

								$fields .= $this->getFieldXML( $value );
							}
						$fields .= "</fields>";
					}
					
				} else {
					echo "<b>Error:</b> N&aatilde;o foi setada a conex&aatilde;o com o DB";	
				}
			break;
			
			case 'array':
				$fields .= "<fields>";

				// arShow( $this->arrayToXml );

				if(is_array($this->arrayToXml)){
					unset($node);
					foreach( $this->arrayToXml  as $key=>$value ){
	 					if(is_array($value)){
		 					$this->setFieldValues( $value );
	 					} else {
	 						$this->setFieldDefaultValues( $key );
	 						$this->transient = true;
	 					}
	 					
	 					$node = $this->getFieldXML( $key );
						$fields .= $node;
					}
				}
				$fields .= "</fields>";				
			break;
		}
		
		return $fields;
	}
	
	public function getEntityXML( $mode = 'data_base' ){
		$entity .= "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
		$entity .= "\n\t<entity name=\"".$this->getTableName()."\">";

		$entity .= $this->getXmlConfigs( $mode );
		$entity .= $this->getXmlFields( $mode );

		$entity .= "\n\t</entity>";
		
		return $entity;
	}
	
}
?>